package com.huaxin.device.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huaxin.device.dto.ResponseCode;
import com.huaxin.device.dto.ResponseResult;
import com.huaxin.device.dto.request.ElectricalRoomCreateReqDTO;
import com.huaxin.device.dto.request.ElectricalRoomPageListReqDTO;
import com.huaxin.device.dto.request.ElectricalRoomUpdateReqDTO;
import com.huaxin.device.dto.response.ElectricalRoomWithStatisticDTO;
import com.huaxin.device.feignClients.InspectionFeignService;
import com.huaxin.device.mapper.ElectricalEquipmentMapper;
import com.huaxin.device.mapper.ElectricalRoomMapper;
import com.huaxin.device.mapper.EquipmentDataSourceMapper;
import com.huaxin.device.mapper.SwitchCabinetMapper;
import com.huaxin.device.mapping.ElectricalRoomMapping;
import com.huaxin.device.models.ElectricalRoom;
import com.huaxin.device.service.ElectricalRoomService;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.webjars.NotFoundException;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.springframework.util.StringUtils.hasText;

@Service
@RequiredArgsConstructor
public class ElectricalRoomServiceImpl extends ServiceImpl<ElectricalRoomMapper, ElectricalRoom> implements ElectricalRoomService {

    private final ApplicationContext applicationContext;
    private final ElectricalRoomMapping mapping;
    private final ElectricalRoomMapper mapper;
    private final ElectricalEquipmentMapper electricalEquipmentMapper;
    private final SwitchCabinetMapper switchCabinetMapper;
    private final EquipmentDataSourceMapper equipmentDataSourceMapper;
    private final InspectionFeignService inspectionFeignService;

    @Override
    public ResponseResult<ElectricalRoom> create(ElectricalRoomCreateReqDTO in) {
        if (in == null) {
            return ResponseResult.parameterError(null, "参数错误");
        }

        // 校验 roomCode + familyId + orgId 是否已存在
        if (existsByFields(ElectricalRoom::getRoomCode, in.getRoomCode(), in.getFamilyId(), in.getOrgId(), null)) {
            return ResponseResult.failure(ResponseCode.CUSTOM_BUSINESS_ERROR, "编号已存在", null);
        }
        // 校验 roomName + familyId + orgId 是否已存在
        if (existsByFields(ElectricalRoom::getRoomName, in.getRoomName(), in.getFamilyId(), in.getOrgId(), null)) {
            return ResponseResult.failure(ResponseCode.CUSTOM_BUSINESS_ERROR, "名称已存在", null);
        }

        ElectricalRoom entity = mapping.toEntity(in);
        if (!save(entity)) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, "添加失败，请稍后再试！", null);
        }
        return ResponseResult.ok(this.getById(entity.getId()));
    }

    @Override
    public ElectricalRoom getByElectricalRoomId(String id) {
        if (id == null || id.isBlank()) {
            throw new IllegalArgumentException("ID不能为空");
        }
        ElectricalRoom entity = this.getById(id);
        if (entity == null) {
            throw new NotFoundException("配电房不存在");
        }
        return entity;
    }

    @Override
    public ResponseResult<String> update(ElectricalRoomUpdateReqDTO in) {
        if (in == null) {
            return ResponseResult.parameterError(null, "参数错误");
        }

        ElectricalRoom entity = getByElectricalRoomId(in.getId());

        // 校验 roomCode + familyId + orgId 是否已存在（不包含当前ID）
        if (existsByFields(ElectricalRoom::getRoomCode, in.getRoomCode(), in.getFamilyId(), in.getOrgId(), in.getId())) {
            return ResponseResult.failure(ResponseCode.CUSTOM_BUSINESS_ERROR, "编号已存在", null);
        }
        // 校验 roomName + familyId + orgId 是否已存在（不包含当前ID）
        if (existsByFields(ElectricalRoom::getRoomName, in.getRoomName(), in.getFamilyId(), in.getOrgId(), in.getId())) {
            return ResponseResult.failure(ResponseCode.CUSTOM_BUSINESS_ERROR, "名称已存在", null);
        }

        mapping.updateEntity(in, entity);
        if (!updateById(entity)) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, "更新失败，请稍后再试！", null);
        }
        return ResponseResult.ok("更新成功");
    }

    @Override
    public ResponseResult<String> delete(String id) {
        ElectricalRoom entity = getByElectricalRoomId(id);

        // 检查该配电房下是否有设备
        if (electricalEquipmentMapper.existsByRoomId(id)) {
            return ResponseResult.failure(ResponseCode.CUSTOM_BUSINESS_ERROR, "该配电房下有设备，请先删除设备", null);
        }

        // 检查该配电房下是否有变电箱
        if (switchCabinetMapper.existsByRoomId(id)) {
            return ResponseResult.failure(ResponseCode.CUSTOM_BUSINESS_ERROR, "该配电房下有变电箱，请先删除变电箱", null);
        }

        boolean removed = this.applicationContext.getBean(ElectricalRoomService.class).removeById(id);
        if (!removed) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, "删除失败，请稍后重试", null);
        }
        return ResponseResult.ok("删除成功！");
    }

    @Override
    public ResponseResult<IPage<ElectricalRoom>> pageQuery(ElectricalRoomPageListReqDTO in) {
        if (in == null) {
            return ResponseResult.parameterError(null, "参数错误");
        }

        IPage<ElectricalRoom> page = new Page<>(in.getPageNum(), in.getPageSize());
        LambdaQueryWrapper<ElectricalRoom> wrapper = new LambdaQueryWrapper<>();

        if (hasText(in.getRoomName())) {
            wrapper.like(ElectricalRoom::getRoomName, in.getRoomName());
        }
        if (hasText(in.getRoomCode())) {
            wrapper.eq(ElectricalRoom::getRoomCode, in.getRoomCode());
        }
        if (hasText(in.getFloor())) {
            wrapper.eq(ElectricalRoom::getFloor, in.getFloor());
        }
        if (in.getFireRating() != null) {
            wrapper.eq(ElectricalRoom::getFireRating, in.getFireRating());
        }
        if (hasText(in.getOrgId())) {
            wrapper.eq(ElectricalRoom::getOrgId, in.getOrgId());
        }
        if (hasText(in.getFamilyId())) {
            wrapper.eq(ElectricalRoom::getFamilyId, in.getFamilyId());
        }

        wrapper.orderByDesc(ElectricalRoom::getCreatedAt);
        IPage<ElectricalRoom> resultPage = this.page(page, wrapper);
        return ResponseResult.ok(resultPage);
    }

    @Override
    public ResponseResult<List<ElectricalRoom>> listByIds(List<String> ids) {
        if (ids == null || ids.isEmpty()) {
            return ResponseResult.ok(List.of());
        }
        LambdaQueryWrapper<ElectricalRoom> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(ElectricalRoom::getId, ids);
        return ResponseResult.ok(list(wrapper));
    }

    @Override
    public ResponseResult<IPage<ElectricalRoomWithStatisticDTO>> pageQueryWithStats(Integer pageNum, Integer pageSize, String orgId, String inspectionOrderId) {

        // 1. 构建分页对象
        Page<ElectricalRoom> page = new Page<>(pageNum, pageSize);

        // 2. 构建查询条件
        LambdaQueryWrapper<ElectricalRoom> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ElectricalRoom::getIsDeleted, 0).eq(ElectricalRoom::getOrgId, orgId);

        // 3. 执行分页查询
        IPage<ElectricalRoom> roomPage = this.page(page, wrapper);

        // 4. 提取配电房 ID 列表，用于后续统计
        List<String> roomIds = roomPage.getRecords().stream()
                .map(ElectricalRoom::getId)
                .collect(Collectors.toList());

        if (roomIds.isEmpty()) {
            // 返回空分页
            return ResponseResult.ok(new Page<>(pageNum, pageSize));
        }

        // 5. 查询每个配电房的配电箱数量
        Map<String, Integer> cabinetCountMap = new HashMap<>();
        List<Map<String, Object>> cabinetCounts = switchCabinetMapper.countCabinetsByRoomIds(roomIds);
        cabinetCounts.forEach(m -> cabinetCountMap.put((String) m.get("room_id"), ((Number) m.get("count")).intValue()));

        // 6. 查询每个配电房关联的采集设备数量（通过 equipment_data_source）
        Map<String, Integer> collectorCountMap = new HashMap<>();
        List<Map<String, Object>> collectorCounts = equipmentDataSourceMapper.countCollectorsByRoomIds(roomIds);
        collectorCounts.forEach(m -> collectorCountMap.put((String) m.get("room_id"), ((Number) m.get("count")).intValue()));

        // 7. 查询巡检项统计
        Map<String, Integer> totalInspectionMap = new HashMap<>();
        Map<String, Integer> completedInspectionMap = new HashMap<>();
        List<Map<String, Object>> inspectionStats = inspectionFeignService.countItemsByRoomIds(roomIds, inspectionOrderId);
        inspectionStats.forEach(m -> {
            String roomId = (String) m.get("room_id");
            totalInspectionMap.put(roomId, ((Number) m.get("total")).intValue());
            completedInspectionMap.put(roomId, ((Number) m.get("completed")).intValue());
        });

        // 8. 转换为 ElectricalRoomWithStatisticDTO 列表
        List<ElectricalRoomWithStatisticDTO> records = roomPage.getRecords().stream()
                .map(room -> {
                    ElectricalRoomWithStatisticDTO dto = new ElectricalRoomWithStatisticDTO();
                    // 复制所有字段
                    org.springframework.beans.BeanUtils.copyProperties(room, dto);

                    // 设置统计字段
                    dto.setCabinetCount(cabinetCountMap.getOrDefault(room.getId(), 0));
                    dto.setCollectorCount(collectorCountMap.getOrDefault(room.getId(), 0));
                    dto.setTotalInspectionItemCount(totalInspectionMap.getOrDefault(room.getId(), 0));
                    dto.setCompletedInspectionItemCount(completedInspectionMap.getOrDefault(room.getId(), 0));

                    return dto;
                })
                .collect(Collectors.toList());

        // 9. 构建返回的分页对象
        IPage<ElectricalRoomWithStatisticDTO> resultPage = new Page<>();
        resultPage.setCurrent(roomPage.getCurrent());
        resultPage.setSize(roomPage.getSize());
        resultPage.setTotal(roomPage.getTotal());
        resultPage.setRecords(records);

        return ResponseResult.ok(resultPage);
    }

    /**
     * 检查多个字段值组合是否已存在（排除当前ID）
     *
     * @param fieldGetter 字段Getter
     * @param fieldValue  字段值
     * @param familyId    家庭ID
     * @param orgId       组织ID
     * @param excludeId   要排除的ID（可为null）
     * @return 是否存在匹配记录
     */
    private boolean existsByFields(
            SFunction<ElectricalRoom, ?> fieldGetter,
            Object fieldValue,
            String familyId,
            String orgId,
            String excludeId) {

        if (fieldGetter == null) return false;

        LambdaQueryWrapper<ElectricalRoom> wrapper = new LambdaQueryWrapper<>();

        if (fieldValue == null ||
                (fieldValue instanceof CharSequence cs && cs.toString().trim().isEmpty())) {
            wrapper.and(wrapper1 -> wrapper1
                    .isNull(fieldGetter)
                    .or().eq(fieldGetter, "")
            );
        } else {
            wrapper.eq(fieldGetter, fieldValue.toString().trim());
        }

        if (familyId == null || familyId.trim().isEmpty()) {
            wrapper.and(wrapper1 -> wrapper1
                    .isNull(ElectricalRoom::getFamilyId)
                    .or().eq(ElectricalRoom::getFamilyId, "")
            );
        } else {
            wrapper.eq(ElectricalRoom::getFamilyId, familyId.trim());
        }

        if (orgId == null || orgId.trim().isEmpty()) {
            wrapper.and(wrapper1 -> wrapper1
                    .isNull(ElectricalRoom::getOrgId)
                    .or().eq(ElectricalRoom::getOrgId, "")
            );
        } else {
            wrapper.eq(ElectricalRoom::getOrgId, orgId.trim());
        }

        if (excludeId != null && !excludeId.trim().isEmpty()) {
            wrapper.ne(ElectricalRoom::getId, excludeId.trim());
        }

        return this.count(wrapper) > 0;
    }
}